﻿#region

using System;
using System.Collections.Concurrent;
using PTCN.CrossPlatform.BettingGame.DataAccess;
using PTCN.CrossPlatform.BettingGame.DataAccess.DAO;
using PTCN.CrossPlatform.BettingGame.Bingo.Models;

#endregion

namespace PTCN.CrossPlatform.BettingGame.Bingo.Factories
{
    public class SedieGameFactory
    {
        protected ConcurrentDictionary<int, bool> _names = new ConcurrentDictionary<int, bool>();
        protected IBettingGameDAO _bettingGameDAO = AbstractDAOFactory.Instance().CreateBettingGameDAO();

        internal SedieGameFactory()
        {
            for (int i = 1; i <= 2000; i++)
            {
                _names.TryAdd(i, false);
            }
        }

        public SedieRoom CreateSession(int minBet, byte moneyType, byte rule, string password, bool solo)
        {
            if (minBet < 0 || moneyType > 1 || rule > (byte) SedieRules.Normal)
            {
                return null;
            }

            int name = GetName();
            if (name < 1)
            {
                return null;
            }

            SedieRoom session = new SedieRoom(minBet, moneyType, password, rule);

            session.Name = name.ToString();
            long sessID = _bettingGameDAO.CreateRoom(name, session.GameId, moneyType, minBet, session.BetStep,
                session.MaxBet, password, rule);
            if (sessID < 1)
            {
                session = null;
            }
            else
            {
                session.SessionId = sessID;
            }

            if (session == null)
            {
                RemoveName(name.ToString());
            }

            return session;
        }

        public SedieGameLoop CreateGameLoop(SedieRoom session)
        {
            if (session != null)
            {
                return new SedieGameLoop(session);
            }
            return null;
        }

        public void RemoveName(string strName)
        {
            int name = -1;
            if (Int32.TryParse(strName, out name))
            {
                if (_names.ContainsKey(name))
                {
                    _names.AddOrUpdate(name, false, (_k, _v) => _v = false);
                }
            }
        }

        protected int GetName()
        {
            foreach (var key in _names.Keys)
            {
                bool value = false;
                if (_names.TryGetValue(key, out value))
                {
                    if (!value)
                    {
                        _names.AddOrUpdate(key, true, (_k, _v) => _v = true);
                        return key;
                    }
                }
            }
            return -1;
        }
    }
}